(function () {
    var boardContainer = $("#board-container");
    var playerBoxes = $("#player-container .player");
    var playerIds = State.scorer.getPlayerIds();

    var trackClaimsLayer = new Kinetic.Layer({
        "name": "trackClaims"
    });
    State.stage.add(trackClaimsLayer);

    // Wire reset to clear visual track claims.
    Events.reset.on(function () {
        trackClaimsLayer.removeChildren();
        trackClaimsLayer.draw();
    });

    // Helper functions.
    var claimTrack = function (track, playerId, trainCarImage) {
        State.scorer.claim(track.getTrack(), playerId);

        track.hide();

        $.each(track.segments, function (index, segment) {
            var image = new Kinetic.Image({
                "image": trainCarImage,
                "x": segment.rect.getX(),
                "y": segment.rect.getY(),
                "width": 10,
                "height": 31,
                "rotationDeg": segment.rect.getRotationDeg(),
                "shadow": {
                    "color": "black",
                    "blur": 3,
                    "opacity": .5,
                    "offset": [3, 3]
                }
            });

            trackClaimsLayer.add(image);
        });

        trackClaimsLayer.draw();
    };

    // Hook up claim methods.
    var activePlayer = undefined;
    var tracksToClaim = undefined;
    $.each(playerBoxes, function (index, playerBox) {
        playerBox = $(playerBox);

        var playerId = playerIds[index];
        var playerData = Data.players[index];

        var trainCarImage = new Image();
        trainCarImage.src = "img/" + playerData.color + "-traincar.png";

        var onTrackEntered = function (track) {
            document.body.style.cursor = "pointer";

            if (tracksToClaim.indexOf(track) === -1) {
                track.highlight();
            }
        };

        var onTrackExited = function (track) {
            document.body.style.cursor = "";

            if (tracksToClaim.indexOf(track) === -1) {
                track.lowlight();
            }
        };

        // Clicking / tapping claim.
        var onClickedTrack = function (track) {
            var index = tracksToClaim.indexOf(track);
            if (index === -1) {
                // Adding track claim.
                tracksToClaim.push(track);
                track.highlight(playerData.color);
                track.getFrom().highlight(playerData.color);
                track.getTo().highlight(playerData.color);

            } else {
                // Removing track claim.
                tracksToClaim.splice(index, 1);
                track.lowlight();

                // Only lowlight cities if some other track isn't including them.
                if (!tracksToClaim.some(function (claim) { return claim.getFrom() === track.getFrom() || claim.getTo() == track.getFrom(); })) {
                    track.getFrom().lowlight();
                }
                if (!tracksToClaim.some(function (claim) { return claim.getFrom() === track.getTo() || claim.getTo() === track.getTo(); })) {
                    track.getTo().lowlight();
                }
            }
        };

        var onPlayerBoxSelected = function () {
            if (activePlayer !== undefined) {
                playerBox.one("click", onPlayerBoxSelected);
                return;
            }

            activePlayer = playerId;
            tracksToClaim = [];
            playerBox.one("click", onPlayerBoxUnselected);
            Events.track.clicked.on(onClickedTrack);
            Events.track.tapped.on(onClickedTrack);
            Events.track.entered.on(onTrackEntered);
            Events.track.exited.on(onTrackExited);

            playerBoxes.animate({
                "width": 0
            });
            playerBox.stop().animate({
                "width": 300
            });
        };

        var onPlayerBoxUnselected = function () {
            try {
                tracksToClaim.forEach(function (track) {
                    try {
                        claimTrack(track, playerId, trainCarImage);
                    } finally {
                        track.lowlight();
                        track.getFrom().lowlight();
                        track.getTo().lowlight();
                    }
                });
            } finally {
                activePlayer = undefined;
                tracksToClaim = [];
                playerBox.one("click", onPlayerBoxSelected);
                Events.track.clicked.off(onClickedTrack);
                Events.track.tapped.off(onClickedTrack);
                Events.track.entered.off(onTrackEntered);
                Events.track.exited.off(onTrackExited);

                playerBoxes.animate({
                    "width": 60
                });
            }
        };

        playerBox.one("click", onPlayerBoxSelected);
    });
}());
